package com.youlu.campus.service.linker.impl;

import com.alibaba.fastjson.JSON;
import com.google.common.collect.Lists;

import com.youlu.campus.common.utils.TimeUtils;
import com.youlu.campus.entity.ShortUrlConfig;
import com.youlu.campus.entity.ShortUrlConfigStatistics;
import com.youlu.campus.entity.VO.req.ShortUrlConfigStatisticsQueryVO;
import com.youlu.campus.service.linker.ShortUrlConfigService;
import com.youlu.campus.service.linker.ShortUrlConfigStatisticsService;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Sort;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.data.mongodb.core.query.Criteria;
import org.springframework.data.mongodb.core.query.Query;
import org.springframework.data.mongodb.core.query.Update;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Objects;

@Slf4j
@Service
public class ShortUrlConfigStatisticsServiceImpl implements ShortUrlConfigStatisticsService {
    @Autowired
    private MongoTemplate mongoTemplate;
    @Autowired
    private RedisTemplate<String, String> redisTemplate;
    @Autowired
    private ShortUrlConfigService shortUrlConfigService;

    private String SHORT_URL_COUNTER = "com.luyou.short-url.counter.%s";

    @Override
    public void incr(String key) {
        log.info(":>>> 开始统计短链接:{}", key);
        ShortUrlConfig config = shortUrlConfigService.findByKey(key);
        if (Objects.isNull(config)) {
            log.error(":>>> 短链接:{} 不存在", key);
            return;
        }
        String Pkey = String.format(SHORT_URL_COUNTER, config.getId());
        Long counter = redisTemplate.opsForValue().increment(Pkey);
        log.info(":>>> 短链接:{} 访问数量:{}", key, counter);
    }

    @Async
    @Override
    public void incShortUrlAndAddConfigStatistics(String shortUrl,String id, Long incr) {
        this.incr(shortUrl);
        this.shortUrlConfigStatistics(id,incr);
    }


    @Override
    public void shortUrlConfigStatistics(String id, Long incr) {
        Date date = new Date();
        List<String> keyList = Lists.newArrayList("MI","H","D","M","Y");
        for (String s : keyList) {
            try {
                this.incr(id,s,date,incr);
            }catch (Exception e){
                log.error(":>>> 更新短链接统计数据错误:{}", e);
            }
        }
    }

    @Override
    public Long getCounter(String id) {
        String Pkey = String.format(SHORT_URL_COUNTER, id);
        Long counter = redisTemplate.opsForValue().increment(Pkey, 0);
        if (Objects.isNull(counter)) {
            return 0L;
        }
        return counter;
    }

    @Override
    public void create(ShortUrlConfigStatistics req) {
        req.setId(null);
        req.setCreatedTime(new Date());
        mongoTemplate.insert(req);
    }


    @Override
    public void incr(String id, String type, Date date, Long incr) {
        if (StringUtils.isBlank(id) || StringUtils.isBlank(type) || Objects.isNull(date)) {
            log.error(":>>> 统计短链接参数错误");
            return;
        }
//        类型,MI:分钟,H:小时,D:日,M:月:Y:年
        Date d = null;
        String timeStr = "";
        switch (type) {
            case "MI":
                d = TimeUtils.getMinuteBegin(date);
                timeStr = TimeUtils.parse(d, "yyyy-MM-dd HH:mm");
                break;
            case "H":
                d = TimeUtils.getHourBegin(date);
                timeStr = TimeUtils.parse(d, "yyyy-MM-dd HH");
                break;
            case "D":
                d = TimeUtils.getDayBegin();
                timeStr = TimeUtils.parse(d, "yyyy-MM-dd");
                break;
            case "M":
                d = TimeUtils.getBeginDayOfMonth(date);
                timeStr = TimeUtils.parse(d, "yyyy-MM");
                break;
            case "Y":
                d = TimeUtils.getBeginDayOfYear();
                timeStr = TimeUtils.parse(d, "yyyy");
                break;
            default:
                break;
        }
        if (Objects.isNull(d)) {
            log.error(":>>> 短链接统计类型错误");
            return;
        }
        ShortUrlConfigStatistics s = this.find(id, type, d);

        if (Objects.isNull(s)) {
            s = new ShortUrlConfigStatistics();
            s.setCounter(incr);
            s.setShortUrlConfigId(id);
            s.setTimeStr(timeStr);
            s.setTime(d);
            s.setType(type);
            this.create(s);
            return;
        }
        Query query = new Query().addCriteria(Criteria.where("id").is(s.getId()));
        Update update = new Update();
        update.inc("counter", incr);
        update.set("updatedTime", new Date());
        mongoTemplate.updateFirst(query, update, ShortUrlConfigStatistics.class);
    }

    @Override
    public List<ShortUrlConfigStatistics> list(ShortUrlConfigStatisticsQueryVO req) {
        log.info(":>>> 开始获取短链接统计数据:{}", JSON.toJSON(req));
        if (Objects.isNull(req) || StringUtils.isBlank(req.getShortUrlConfigId())) {
            return new ArrayList<>();
        }

        Query query = new Query().addCriteria(Criteria.where("shortUrlConfigId").is(req.getShortUrlConfigId()));
        if (StringUtils.isNotBlank(req.getType())) {
            query.addCriteria(Criteria.where("type").is(req.getType()));
        }
        Criteria criteriaPay = null;
        if (req.getStartTime() != null || req.getEndTime() != null) {
            criteriaPay = Criteria.where("time");
            if (req.getStartTime() != null) {
                criteriaPay.gte(req.getStartTime());
            }
            if (req.getEndTime() != null) {
                criteriaPay.lte(req.getEndTime());
            }
        }
        if (Objects.nonNull(criteriaPay)) {
            query.addCriteria(criteriaPay);
        }
//        query.with(new Sort(Sort.Direction.ASC, "time"));
        Sort sort=Sort.by(Sort.Direction.ASC, "time");
        query.with(sort);
        List<ShortUrlConfigStatistics> datas = mongoTemplate.find(query, ShortUrlConfigStatistics.class);
        return datas;
    }

    @Override
    public ShortUrlConfigStatistics find(String shortUrlConfigId, String type, Date date) {
//        Query query = new Query().addCriteria(Criteria.where("time").is(date).and("type").is(type).and("shortUrlConfigId").is(shortUrlConfigId));
        Query query = new Query().addCriteria(Criteria.where("shortUrlConfigId").is(shortUrlConfigId).and("type").is(type).and("time").is(date));
        return mongoTemplate.findOne(query, ShortUrlConfigStatistics.class);
    }

    @Override
    public String getLongUrl(String longUrl, String type) {
        log.info(":>>> 开始获取长链接:{},{}", longUrl, type);
        /**
         * A:活动,P:收款,QQ:qq群,Wechat:微信群,Email:邮件,Other:其他
         */
        switch (type) {
            case "A":
                break;
            case "P":
                break;
            default:
                break;
        }
        return longUrl;
    }
}
